package org.linlinjava.litemall.wx.service;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.linlinjava.litemall.db.domain.LitemallUserToken;
import org.linlinjava.litemall.db.service.LitemallUserTokenService;
import org.linlinjava.litemall.db.service.UserTokenService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

@Component
public class TokenHelper implements CommandLineRunner, UserTokenService {
	// 秘钥
	static final String SECRET = "X-Litemall-Token";
	// 签名是有谁生成
	static final String ISSUSER = "LITEMALL";

	@Autowired
	private LitemallUserTokenService userTokenService;

	public void saveToken(Integer userId, String token) {
		if (userId == null || StringUtils.isBlank(token)) {
			return;
		}
		DecodedJWT jwt = getTokenDecodedJWT(token);
		if (jwt == null) {
			return;
		}
		LitemallUserToken userToken = userTokenService.findByUid(userId);
		if (userToken == null) {
			userToken = new LitemallUserToken();
			userToken.setUserId(userId);
			userToken.setToken(token);
			userToken.setAddTime(LocalDateTime.now());
			userToken.setUpdateTime(LocalDateTime.now());
			userToken.setExpireDate(dateToTime(jwt.getExpiresAt()));
			userToken.setStatus(true);

			userTokenService.add(userToken);
		} else {
			userToken.setToken(token);
			userToken.setUpdateTime(LocalDateTime.now());
			userToken.setStatus(true);
			userToken.setExpireDate(dateToTime(jwt.getExpiresAt()));

			userTokenService.update(userToken);
		}
		// 更新缓存数据
		TokenCacheManager.loadData(userId, userToken);

	}

	private LocalDateTime dateToTime(Date date) {
		if (date == null) {
			return null;
		}
		try {
			return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime();
		} catch (Exception e) {

		}
		return null;
	}

	public DecodedJWT getTokenDecodedJWT(String token) {
		try {
			Algorithm algorithm = Algorithm.HMAC256(SECRET);
			JWTVerifier verifier = JWT.require(algorithm).withIssuer(ISSUSER).build();
			return verifier.verify(token);
		} catch (JWTVerificationException exception) {
//			exception.printStackTrace();
		}

		return null;
	}

	@Override
	public void run(String... args) throws Exception {
		List<LitemallUserToken> tokenList = userTokenService.queryAll();
		TokenCacheManager.clearAll();
		TokenCacheManager.loadAllData(tokenList);
	}

	@Override
	public void updateUserTokenCatch(List<Integer> userIds) {
		List<LitemallUserToken> tokenList = userTokenService.queryByUserIds(userIds);
		TokenCacheManager.clears(userIds);
		TokenCacheManager.loadAllData(tokenList);
	}

}
